package com.tanger.im;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tanger.common.helper.BatchHelper;
import com.tanger.im.entity.ImUserRecord;
import com.tanger.im.mapper.IMUserRecordRepository;
import org.apache.logging.log4j.util.Strings;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 本数据库IM记录同步
 * @Author Hchenbin
 * @Date 2024-01-02 09:57
 * @Version 1.0
 */
@Component
public class SyncIMDBCacheHandle implements Job {

    @Autowired
    private IMUserRecordRepository repository;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    /**
     * 每日凌晨0点整执行的定时任务:更新数据库聊天记录
     */
    @Override
    public void execute(JobExecutionContext context) {
        //获取所有缓存key
        Set<String> keys = Optional.ofNullable(
                stringRedisTemplate.keys(String.format(CacheKey.IM_USER_RECORD,"*")))
                .orElseGet(Collections::emptySet);

        Map<String,List<ImUserRecord>> group = Optional.ofNullable(
                repository.selectList(new QueryWrapper<ImUserRecord>()))
                .map(rs -> rs.parallelStream()
                        .collect(Collectors.groupingBy(ImUserRecord::getMd5Key)))
                .orElseGet(Collections::emptyMap);

        List<ImUserRecord> updates = new ArrayList<>();
        List<ImUserRecord> inserts = new ArrayList<>();
        //获取value
        keys.parallelStream()
                .forEach(k -> {
                    //获取记录
                    List<ImUserRecord> rs = findValue(k);
                    if (CollectionUtils.isEmpty(rs)) {
                        rs.parallelStream()
                                .forEach(v -> {
                                    if (group.containsKey(v.getMd5Key())) {
                                        updates.add(v);
                                    } else {
                                        inserts.add(v);
                                    }
                                });
                    }
                });
        if (!CollectionUtils.isEmpty(updates)) {
            Map<Integer, List<ImUserRecord>> mapBatch = BatchHelper.collectionAndBatchProcessing(inserts);
            Iterator<Map.Entry<Integer, List<ImUserRecord>>> it = mapBatch.entrySet().iterator();
            while (it.hasNext()) {
                repository.batchUpdate(it.next().getValue());
            }
        }
        if (!CollectionUtils.isEmpty(inserts)) {
            Map<Integer, List<ImUserRecord>> mapBatch = BatchHelper.collectionAndBatchProcessing(inserts);
            Iterator<Map.Entry<Integer, List<ImUserRecord>>> it = mapBatch.entrySet().iterator();
            while (it.hasNext()) {
                repository.batchInsert(it.next().getValue());
            }
        }
    }

    protected List<ImUserRecord> findValue(String key) {
        if (!Strings.isEmpty(key)) {
            String data = stringRedisTemplate.opsForValue().get(key);
            return JSONObject.parseArray(data,ImUserRecord.class);
        }
        return null;
    }
}
